﻿/* *
 * =============================================================================
 * File Name:               SlideShow.cs
 * Programmer:              Ken Watts
 * Creation Date:           10/20/2008
 * =============================================================================
 * Description:             Class that represents a SlideShow.cs
 * =============================================================================
 * Modification Date:       10/20/2008 - Initial Revision
 * =============================================================================
 * */
using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace SlideShowViewer
{
    public class SlideShow : Canvas
    {
        // Private constants
        private const int k_int_display_images = 2;
        private const int k_int_bottom_image = 0;
        private const int k_int_top_image = 1;
        private const int k_int_default_transition_frames = 10;
        private const int k_int_default_transition_interval_ms = 100;

        // Constant transition definintions
        public const int k_int_transition_none = 0;
        public const int k_int_transition_random = 1;
        public const int k_int_transition_cross_fade = 2;

        // Private data
        private int imageCount = 0;
        private int currentImage = 0;
        private int frameCount;
        private int currentTransition;
        private Canvas[] slideShowCanvases = new Canvas[k_int_display_images];
        private Image[] slideShowImages = new Image[k_int_display_images];
        private List<String> imageList;
        private List<int> displayOrderList;
        private DispatcherTimer timer=new DispatcherTimer();

        // Public data
        public int transitionType = k_int_transition_cross_fade;//k_int_transition_none;
        public int transitionFrames = k_int_default_transition_frames;
        public int transitionIntervalMs = k_int_default_transition_interval_ms;

        public SlideShow(Panel parentPanel, int width, int height)
        {
            imageList = new List<string>();
            // Initialize display images
            for (int i = k_int_display_images - 1; i >= 0; i--)
            {
                slideShowImages[i] = new Image();
                slideShowImages[i].Width = width;
                slideShowImages[i].Height = height;
                slideShowCanvases[i] = new Canvas();
                slideShowCanvases[i].Width = width;
                slideShowCanvases[i].Height = height;
                slideShowCanvases[i].Background = new SolidColorBrush(Color.FromArgb(0xff, 0xff, 0xff, 0xff));
                slideShowCanvases[i].Children.Add(slideShowImages[i]);
                parentPanel.Children.Add(slideShowCanvases[i]);
            }
            // Initialze the timer
            timer.Interval = new TimeSpan(0, 0, 0, 0, transitionIntervalMs);
            timer.Tick += new EventHandler(TimerTick);
        }

        public void AddImage(String imageFileName)
        {
            // Add the image
            imageList.Add(imageFileName);
            imageCount++;
        }

        public void BeginShow(bool shuffle)
        {
            displayOrderList = new List<int>();
            Random rand = new Random(DateTime.Now.Millisecond);

            // Initialize the display order list
            for (int i = 0; i < imageCount; i++)
                displayOrderList.Add(i);
            // Shuffle the display order if shuffle is set
            if (shuffle)
            {
                for (int i = 0; i < imageCount; i++)
                {
                    int swap=rand.Next(imageCount);
                    int tmp = displayOrderList[swap];
                    displayOrderList[swap] = displayOrderList[i];
                    displayOrderList[i] = tmp;
                }
            }

            if (imageCount > 0)
            {
                // Set up the images
                slideShowImages[currentImage % k_int_display_images].Source =
                    new BitmapImage(new Uri(imageList[displayOrderList[currentImage++ % imageCount]], UriKind.Relative));
                slideShowImages[currentImage % k_int_display_images].Source =
                    new BitmapImage(new Uri(imageList[displayOrderList[currentImage++ % imageCount]], UriKind.Relative));
            }
        }

        private void ShowNextImage()
        {
            // Display the next image
            slideShowCanvases[currentImage % k_int_display_images].SetValue(Canvas.ZIndexProperty, k_int_bottom_image);
            slideShowCanvases[currentImage % k_int_display_images].Opacity = 1;
            // Load the next image
            slideShowImages[currentImage % k_int_display_images].Source =
                new BitmapImage(new Uri(imageList[displayOrderList[currentImage++ % imageCount]], UriKind.Relative));
            // Display the next image
            slideShowCanvases[currentImage % k_int_display_images].SetValue(Canvas.ZIndexProperty, k_int_top_image);
        }

        public void Next()
        {
            if ((imageCount > 0)&&!timer.IsEnabled)
            {
                if (transitionType == k_int_transition_none)
                {
                    ShowNextImage();
                }
                else
                {
                    // Do the transition
                    frameCount = 0;
                    // If the transition type is "Random", pick a random transition
                    currentTransition = transitionType;
                    timer.Start();
                }
            }
        }

        void TimerTick(object sender, EventArgs e)
        {
            switch (currentTransition)
            {
                case k_int_transition_cross_fade:
                    // Adjust the alpha channel
                    slideShowCanvases[currentImage % k_int_display_images].Opacity = 1 - ((double)frameCount / (double)transitionFrames);
                    break;
                default:
                    break;
            }
            // Stop the timer if all frames have been transitioned
            if (++frameCount == transitionFrames)
            {
                timer.Stop();
                ShowNextImage();
            }
        }
    }
}
